package edu.fau.scanny.r.stromal;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.BeanToPropertyValueTransformer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;

import edu.fau.scanny.r.RBioconductorUtils;
import edu.fau.scanny.r.RFactory;
import edu.fau.scanny.r.RUtils;
import edu.fau.scanny.r.stromal.model.CelFile;
import edu.fau.scanny.r.stromal.model.GroupOutput;
import edu.fau.scanny.r.stromal.model.HeatMap;
import edu.fau.scanny.r.stromal.model.IdTable;
import edu.fau.scanny.r.stromal.model.StromalCalculatorModel;
import edu.fau.scanny.r.stromal.model.StromalOutput;
import edu.fau.scanny.r.stromal.servlet.GlobalVariables;
import edu.fau.scanny.r.stromal.servlet.WebPageStringUtils;
import edu.fau.scanny.stromal.MetaFileUtils;

public class RStromalFactory {

	public enum Normalize {
		MAS5, RMA, PLIER, PLIER16
	}

	public enum Tissue {
		WHOLE, PART
	}

	// rows in id table do not need to be in same order as in cel files
	// merge? expression table is a matrix and would have to be converted to a
	// data.frame
	// alternative: use match
	// tmp1 <- match(rownames(tableVarName), rownames(idTable) )
	// st3 <- cbind( idTable[tmp1,
	// c(idTable.getGeneCol(),idTable.getEntrezCol())] , normData2 )
	public static void addGeneEntrezIds(RConnection rc, String tableVarName, IdTable idTable) throws REngineException, REXPMismatchException {
		String match = "tmp";
		RUtils.assign(rc, RUtils.match(RUtils.rownames(tableVarName), RUtils.rownames(idTable.getrTableVar())), match);

		List<String> tables = new ArrayList<String>();
		tables.add(String.format("%s[%s,c(%s,%s)]", idTable.getrTableVar(), match, idTable.getGeneCol(), idTable.getEntrezCol()));
		tables.add(tableVarName);
		RUtils.cbind(rc, tables, tableVarName);
	}

	public static void addNewColumn(RConnection rc, String tableVar, Integer column, String label) throws REngineException, REXPMismatchException {

		RUtils.asMatrix(rc, RUtils.tableRowsColsSelection(tableVar, "", column.toString()), label);
		RUtils.runRExp(rc, String.format("c(\"%s\")->colnames(%s)", label, label));
		RUtils.assignRowNames(rc, tableVar, label);

	}

	public static void addNewColumn(RConnection rc, String tableVar, Integer column, String filterVar, String label) throws REngineException,
			REXPMismatchException {
		RUtils.asMatrix(rc, String.format("%s[,%s]", tableVar, column), label);
		RUtils.runRExp(rc, String.format("c(\"%s\")->colnames(%s)", label, label));
		RUtils.assignRowNames(rc, tableVar, label);
	}

	public static void averageFile(RConnection rc, Map<String, List<CelFile>> groupFilesMap, String normDataVarName, String timeGroupVar,
			List<String> bindingOrder) throws REngineException, REXPMismatchException {
		System.out.println("## Averaging Signals: " + timeGroupVar);
		List<String> tables = new ArrayList<String>();
		for (String type : bindingOrder) {
			String columnName = timeGroupVar + "." + StringUtils.replace(type.toString(), " ", "");
			List<CelFile> cFiles = groupFilesMap.get(type);
			if (cFiles.size() > 1) {
				BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("chipFile");
				List<String> chips = (List<String>) CollectionUtils.collect(cFiles, transformer);
				RUtils.average(rc, chips, normDataVarName, columnName);
			} else {
				String getColumn = String.format("%s[ , c(\"%s\")]->%s", normDataVarName, cFiles.get(0).getChipFile(), columnName);
				System.out.println(getColumn);
				rc.parseAndEval(getColumn);
				RUtils.frameFunction(rc, columnName, columnName);
				RUtils.assignRowNames(rc, normDataVarName, columnName);
			}

			tables.add(columnName);
		}
		RUtils.cbind(rc, tables, timeGroupVar);
	}

	public static void calculatedStromal(RConnection rc, String tableVar, String plymphoid, String calculatedStromalVar) throws REngineException,
			REXPMismatchException {
		System.out.println("#### Calculate Stromal Signal");
		String calculatedStromalFxn = String.format("%s<-(%s[,1]-%s*%s[,2])/(1-%s)", calculatedStromalVar, tableVar, plymphoid, tableVar, plymphoid);
		RUtils.runRExp(rc, calculatedStromalFxn);
		RUtils.frameFunction(rc, calculatedStromalVar, calculatedStromalVar);
		RUtils.assignRowNames(rc, tableVar, calculatedStromalVar);
	}

	public static void calculatedStromalTargetNormalize(RConnection rc, String tableVar, String calculatedStromalVar) throws REngineException,
			REXPMismatchException {

	}

	// rankorderedratio needs to be calculated first
	// x2<-c(1:length(orderedratio));
	// eq<<-polyfit(x2,orderedratio,3);
	public static void eq(RConnection rc, String orderedRatio, String eqVar) throws REngineException, REXPMismatchException {
		String x2 = String.format("x2<-c(1:length(%s));", orderedRatio);
		System.out.println(x2);
		rc.parseAndEval(x2);
		String eq = String.format("%s<<-polyfit(x2,%s,3);", eqVar, orderedRatio);
		System.out.println(eq);
		rc.parseAndEval(eq);
	}

	public static StromalOutput getStromalOutput(RConnection rc, File boxPlotFile, File comparisonPlotFile, String presentCallVar,
			String wholePartVar, String value, String normMethod, boolean log2, String calculatedStromal, File mskPlotFile, String mskList,
			String lymphSpecific, String stromalSpecific) throws REngineException,
			REXPMismatchException, IOException {

		System.out.println("## Stromal Output " + wholePartVar);
		StromalOutput so = new StromalOutput();
		so.setPercentLymphoid(Double.parseDouble(value));
		so.setPresentCallPercentS(presentCallVar);

		List<String> tables = new ArrayList<String>();
		tables.add(wholePartVar);
		tables.add(calculatedStromal);

		String combined = "averageAndStromal." + wholePartVar;
		RUtils.cbind(rc, tables, combined);

		List<String> xlabels = Arrays.asList(new String[] { "Whole Tissue", "Lymphocyte", "Calc.Stroma" });

		String plymphoidTitle = String.format("(P-lymphoid = %s)", so.getPercentLymphoid());
		String comparisonTitle = "Distribution of Stromal vs Lymphoid Markers\n" + plymphoidTitle;
		File comparisonPlot = RStromalPlotFactory.comparisonPlotter(rc, comparisonPlotFile, combined, true, comparisonTitle, xlabels, normMethod,
				lymphSpecific, stromalSpecific);
		so.setComparisonPlot(comparisonPlot);

		String mskPlotTitle = "Affy Mask List (100)\n" + plymphoidTitle;
		File mskPlot = RStromalPlotFactory.mskPlot(rc, mskPlotFile, combined, true, mskPlotTitle, xlabels, normMethod, mskList);
		so.setMskPlot(mskPlot);

		qualityControl(rc, so, combined, "1", "3",lymphSpecific,stromalSpecific,mskList);
		String boxplotTitle = "Averaged Signal Ranges\n" + plymphoidTitle;
		RStromalPlotFactory.boxPlot(rc, boxPlotFile, combined, true, normMethod + " Signals", xlabels, boxplotTitle, false);
		so.setBoxPlotFile(boxPlotFile);

		Integer precision = 0;
		if (log2) {
			RUtils.assign(rc, RUtils.log2(combined), combined);
			precision = 2;
		}
		RUtils.assign(rc, RUtils.round(combined, precision), combined);

		String wholeTissueS = wholePartVar + ".wholeTissue";
		addNewColumn(rc, combined, 1, wholeTissueS);
		// Double medianWT = RUtils.runRExp(rc, RUtils.median(wholeTissueS,
		// false)).asDouble();
		// Map<Double, Double> quantileWT = getQuantiles(wholeTissueS);
		// Signal wt = new Signal(wholeTissueS, medianWT, quantileWT);
		// so.setWholeTissueS(wt);
		so.setWholeTissueS(wholeTissueS);

		String lymphocyteS = wholePartVar + ".lymphocyte";
		addNewColumn(rc, combined, 2, lymphocyteS);
		so.setLymphocyteS(lymphocyteS);

		String stromalS = wholePartVar + ".stromal";
		addNewColumn(rc, combined, 3, stromalS);
		so.setStromalS(stromalS);

		// for whole, part and stromal to be in one file
		// File stromalFile = RStromalFactory.signalFile(rc, combined,
		// presentCallVar, log2);
		// so.setSignalFile(stromalFile);

		return so;
	}

//	mean(CalculatedStromal.YoungCortex[lymphSpecific]/ YoungCortex[lymphSpecific,1])->lymphSpecificDepletion
//	mean(CalculatedStromal.YoungCortex[StromalList]/YoungCortex[StromalList,1])->StromalSpecificEnrichment
//	mean(CalculatedStromal.YoungCortex[MskList]->CalculatedStromal.YoungCortex.MskListMean
//	sd(CalculatedStromal.YoungCortex[MskList]->CalculatedStromal.YoungCortex.MskListSD
//	mean(YoungCortex[MskList,1])->YoungWholeCortexMskListMean
//	sd(YoungCortex[MskList,1])->YoungWholeCortexMskListSD
	private static void qualityControl(RConnection rc, StromalOutput so, String table, String wholeCol, String stromalCol,
			String lymphSpecific, String stromalSpecific, String mskList) throws REngineException, REXPMismatchException{
		REXP lymphSpecificDepletion = RUtils.runRExp(rc, String.format("mean(%s[%s,%s]/ %s[%s,%s])->lymphSpecificDepletion",table,lymphSpecific, stromalCol, table, lymphSpecific, wholeCol));
		so.setLymphSpecificDepletion(lymphSpecificDepletion.asDouble());
		REXP stromalSpecificEnrichment = RUtils.runRExp(rc, String.format("mean(%s[%s,%s]/ %s[%s,%s])->stromalSpecificEnrichment",table,stromalSpecific, stromalCol, table, stromalSpecific, wholeCol));
		so.setStromalSpecificEnrichment(stromalSpecificEnrichment.asDouble());
		REXP stromalMskMean = RUtils.runRExp(rc, String.format("mean(%s[%s,%s])->stromal.MskListMean", table,mskList, stromalCol));
		so.setStromalMskListMean(stromalMskMean.asDouble());
		REXP stromalMskSD = RUtils.runRExp(rc, String.format("sd(%s[%s,%s])->stromal.MskListSD", table,mskList, stromalCol));
		so.setStromalMskListStandDev(stromalMskSD.asDouble());
		REXP tissueMskMean = RUtils.runRExp(rc, String.format("mean(%s[%s,%s])->tissue.MskListMean", table,mskList,wholeCol));
		so.setTissueMskListMean(tissueMskMean.asDouble());
		REXP tissueMskSD = RUtils.runRExp(rc, String.format("sd(%s[%s,%s])->tissue.MskListSD", table,mskList, wholeCol));
		so.setTissueMskListStandDev(tissueMskSD.asDouble());
	}

	private static Map<Double, Double> getQuantiles(String signal) {
		Map<Double, Double> map = new LinkedHashMap<Double, Double>();

		return map;
	}

	public static StromalOutput getStromalOutputTargetQN(RConnection rc, File boxPlotFile, File comparisonPlotFile, String presentCallVar,
			String wholePartVar, String value, String normMethod, boolean log2, File mskPlotFile, String mskList, String lymphSpecific,
			String stromalSpecific) throws REngineException, REXPMismatchException,
			IOException {

		String calculatedStromal = "CalculatedStromal." + wholePartVar;
		calculatedStromal(rc, wholePartVar, value, calculatedStromal);

		System.out.println("#### Quantile Normalize to Whole Tissue " + wholePartVar);
		RUtils.asMatrix(rc, calculatedStromal, calculatedStromal);
		String normalizeQuantile = String.format("normalize.quantiles.use.target(%s,%s[,1])->%s", calculatedStromal, wholePartVar, calculatedStromal);
		RUtils.runRExp(rc, normalizeQuantile);
		RUtils.assignRowNames(rc, wholePartVar, calculatedStromal);

		StromalOutput so = getStromalOutput(rc, boxPlotFile, comparisonPlotFile, presentCallVar, wholePartVar, value, normMethod, log2,
				calculatedStromal, mskPlotFile, mskList, lymphSpecific, stromalSpecific);

		return so;
	}

	public static void lymphRatio(RConnection rc, String tableVar, String calculatedStromalVar, String lymphRatioVar) throws REngineException,
			REXPMismatchException {
		System.out.println("## Calculating lymph ratio");
		ratio(rc, "lymphSpecific", tableVar, calculatedStromalVar, lymphRatioVar);
	}

	// signal is linearized if normalization produces log2
	public static void normalize(RConnection rc, String sampleVarName, Normalize normalize, String normDataVarName) throws REngineException,
			REXPMismatchException {
		boolean log2 = true;
		switch (normalize) {
		case MAS5:
			RBioconductorUtils.mas5(rc, sampleVarName, normDataVarName);
			log2 = false;
			break;
		case RMA:
			RBioconductorUtils.rma(rc, sampleVarName, normDataVarName);
			break;
		case PLIER:
			RBioconductorUtils.plier(rc, sampleVarName, normDataVarName);
			break;
		case PLIER16:
			RBioconductorUtils.plier(rc, sampleVarName, normDataVarName);
			System.out.println("## Shifting PLIER linear output by 16");
			// linearize signal, then add 16, then log2 signal again for
			// quantile normalization
			RUtils.linearizeLog2(rc, normDataVarName, normDataVarName);
			RUtils.runRExp(rc, String.format("%s=%s+16", normDataVarName, normDataVarName));
			RUtils.assign(rc, RUtils.log2(normDataVarName), normDataVarName);
			break;
		}
		// quantile normalization performed after each normalization option
		RUtils.loadLibrary(rc, "preprocessCore");
		RBioconductorUtils.quantileNormalize(rc, normDataVarName);

		// linearize RMA and PLIER signals
		if (log2)
			RUtils.linearizeLog2(rc, normDataVarName, normDataVarName);

	}

	public static File normalizeFile(RConnection rc, String celFileLocation, StromalCalculatorModel model, String sampleVarName,
			String normDataVarName, IdTable idTable) throws REngineException, REXPMismatchException, IOException {

		List<String> celFilesLocs = new ArrayList<String>();
		List<String> shortNames = new ArrayList<String>();
		shortNames.add("Gene Symbol");
		shortNames.add("Entrez Gene ID");
		shortNames.add("Probe Set ID");
		for (CelFile cf : model.getCelFiles()) {
			celFilesLocs.add(celFileLocation + cf.getChipFile());
			shortNames.add(cf.getShortName());
		}
		RBioconductorUtils.readAffy(rc, sampleVarName, celFilesLocs);
		normalize(rc, sampleVarName, model.getNormalizationMethod(), normDataVarName);

		String normS = model.getNormalizationMethod().toString();
		String format = WebPageStringUtils.log2S(model.isLog2());

		File normFile = File.createTempFile(String.format("norm_%s_%s_", normS, format), ".txt");
		normFile.deleteOnExit();

		String normFileName = normFile.getAbsolutePath().replace("\\", "/");
		String fileNormData = "normData2";
		RUtils.runRExp(rc, fileNormData + "=" + normDataVarName);
		RUtils.colNames(rc, RUtils.combine(shortNames), fileNormData);
		Integer precision = 0;
		if (model.isLog2()) {
			RUtils.assign(rc, RUtils.log2(fileNormData), fileNormData);
			precision = 2;
		}

		RUtils.assign(rc, RUtils.round(fileNormData, precision), fileNormData);

		List<String> tables = new ArrayList<String>();
		tables.add(String.format("rownames(%s)", fileNormData));
		tables.add(fileNormData);
		RUtils.cbind(rc, tables, fileNormData);
		RStromalFactory.addGeneEntrezIds(rc, fileNormData, idTable);
		RUtils.runRExp(rc, String.format("colnames(%s)<-%s", fileNormData, RUtils.combine(shortNames)));
		RUtils.writeTable(rc, fileNormData, normFileName, "TRUE", "FALSE");
		return normFile;
	}

	// plymphLymphSpecific<<-mean(x[lymphSpecific,1]/x[lymphSpecific,2]);
	public static Double plymphLymphSpecific(RConnection rc, String tableVarName, String plymphVarName, String lymphSpecificList)
			throws REngineException, REXPMismatchException {
		System.out.println("## Calculating plymphoid specific");
		String plymphLymphSpecific = String.format("%s<-mean(%s[%s,1]/%s[%s,2]);", plymphVarName, tableVarName, lymphSpecificList, tableVarName,
				lymphSpecificList);
		REXP rexp = RUtils.runRExp(rc, plymphLymphSpecific);
		return rexp.asDouble();
	}

	public static void pLymphLymphSpecific(RConnection rc, String values, String listVariable, String pLymph) throws REngineException,
			REXPMismatchException {
		System.out.println("## Calculating plymphoid specific");
		String calcPL = String.format("mean(%s[%s,1]/%s[%s,2])->%s", values, listVariable, values, listVariable, pLymph);
		System.out.println(calcPL);
		rc.parseAndEval(calcPL);

	}

	public static void quantNormStromalToAllSamples(RConnection rc, List<String> allSignalVars, Map<String, CelFile> chipCelFileMap,
			Map<String, String> calculatedStromals, List<String> bindingOrder) throws REngineException, REXPMismatchException {

		String normAgain = "normDataPlusStromal";
		RUtils.cbind(rc, allSignalVars, normAgain);
		RUtils.asMatrix(rc, normAgain, normAgain);
		RBioconductorUtils.quantileNormalize(rc, normAgain);
		for (String calculatedStromal : calculatedStromals.values()) {
			RUtils.assign(rc, String.format("%s[,c(\"%s\")]", normAgain, calculatedStromal), calculatedStromal);
			RUtils.frameFunction(rc, calculatedStromal, calculatedStromal);
			RUtils.assignRowNames(rc, normAgain, calculatedStromal);
		}

		REXP ex = rc.parseAndEval("colnames(" + GlobalVariables.NORM_DATA + ")");
		String[] chips = ex.asStrings();

		Map<String, Map<String, List<CelFile>>> groupFilesMap = new HashMap<String, Map<String, List<CelFile>>>();
		for (String chip : chips) {
			CelFile celFile = chipCelFileMap.get(chip);
			MetaFileUtils.updateMap(groupFilesMap, celFile.getTime() + " " + celFile.getGroup(), celFile.getType(), celFile);
		}
		for (Entry<String, Map<String, List<CelFile>>> groupEntry : groupFilesMap.entrySet()) {
			String group = groupEntry.getKey();
			Map<String, List<CelFile>> filesMap = groupEntry.getValue();
			String timeGroupVar = StringUtils.replace(group, " ", "");
			RStromalFactory.averageFile(rc, filesMap, normAgain, timeGroupVar, bindingOrder);
		}

	}

	// xforplymph needs to be calculated first
	// plymph<<-polyval(eq,xforplymph);
	public static Double plymphPerpendicular(RConnection rc, String eqVar, String xforplymphVar, String plymphVar) throws REngineException,
			REXPMismatchException {
		System.out.println("## Calculating plymphoid perpendicular");
		String plymphPerpendicular = String.format("%s<<-polyval(%s,%s);", plymphVar, eqVar, xforplymphVar);
		REXP rexp = RUtils.runRExp(rc, plymphPerpendicular);
		return rexp.asDouble();
	}

	// xforplymph and eq need to be calculated first
	// plymphTangent<<- (-m)*xforplymph+plymph;
	public static Double plymphTangent(RConnection rc, String xforplymphVarName, String eqVarName, String plymphPerpendicular, String plymphVarName,
			String slope) throws REngineException, REXPMismatchException {
		System.out.println("## Calculating plymphoid tangent");
		slope(rc, slope, xforplymphVarName, eqVarName);
		String plymphTangent = String.format("%s<<-(-%s)*%s+%s;", plymphVarName, slope, xforplymphVarName, plymphPerpendicular);
		REXP rexp = RUtils.runRExp(rc, plymphTangent);
		return rexp.asDouble();
	}

	// mas5calls(samples[,celNames])->CallData
	// exprs(CallData)->CallData
	// as.data.frame(CallData)->CallData
	// rowSums(CallData=="P")->Ps
	// Ps>(y-1)->MeetCriteria
	// rownames(WholeTissue)[MeetCriteria]->>NewPresentCallList
	public static void presentCallFilter(RConnection rc, List<String> wholeCelFiles, String normDataVar, String sampleTableVar,
			Integer degreesOfFreedom, String presentCallListOutVar) throws REngineException, REXPMismatchException {
		System.out.println("## Present call filter");
		String callData = "CallData";
		RBioconductorUtils.mas5calls(rc, sampleTableVar, RUtils.combine(wholeCelFiles), callData);
		RBioconductorUtils.exprs(rc, callData, callData);
		RUtils.frameFunction(rc, callData, callData);
		String ps = "Ps";
		RUtils.rowSums(rc, callData + "==\"P\"", ps);
		String absent = "absent";
		RUtils.runRExp(rc, String.format("%s<(%s-%s)->%s", ps, wholeCelFiles.size(), degreesOfFreedom, absent));
		String rows = "rows";
		RUtils.rowNames(rc, normDataVar, rows);
		RUtils.runRExp(rc, String.format("%s[%s]->%s", rows, absent, presentCallListOutVar));
	}

	public static void presentCallPercent(RConnection rc, List<String> wholeCelFiles, String normDataVar, String sampleTableVar,
			String presentCallListOutVar) throws REngineException, REXPMismatchException {
		System.out.println("## Present call filter");
		String callData = "CallData";
		RBioconductorUtils.mas5calls(rc, sampleTableVar, RUtils.combine(wholeCelFiles), callData);
		RBioconductorUtils.exprs(rc, callData, callData);
		RUtils.frameFunction(rc, callData, callData);
		RUtils.rowSums(rc, callData + "==\"P\"", presentCallListOutVar);
		RUtils.runRExp(rc, String.format("%s*100/%s->%s", presentCallListOutVar, wholeCelFiles.size(), presentCallListOutVar));
	}

	public static GroupOutput processGroup(RConnection rc, File ratioFile, List<String> bindingOrder, String group,
			Map<String, List<CelFile>> filesMap, String wholeP, String presentCallVarIndv, String normDataVar, String sampleDataVar, String rorPlot,
			String pPer, String pTan, String pLymphSp, String timeGroupVar, String lymphSpecific) throws REngineException, REXPMismatchException,
			IOException {

		GroupOutput go = new GroupOutput();
		// setting R present call variable
		go.setPresentCallVarIndv(presentCallVarIndv);
		String eqVar = "eqVar";
		String xforplymph = "xforplymphVar";

		List<CelFile> wholeCelFiles = (List<CelFile>) filesMap.get(wholeP);
		BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("chipFile");
		Collection wholeChips = CollectionUtils.collect(wholeCelFiles, transformer);

		// percent present call = # samples present in/ # samples
		RStromalFactory.presentCallPercent(rc, (List<String>) wholeChips, normDataVar, sampleDataVar, presentCallVarIndv);

		RStromalFactory.averageFile(rc, filesMap, normDataVar, timeGroupVar, bindingOrder);
		RFactory.rankOrderedRatio(rc, timeGroupVar, rorPlot);
		RStromalFactory.eq(rc, rorPlot, eqVar);
		RStromalFactory.xforplymph(rc, eqVar, xforplymph);
		Double pPerp = RStromalFactory.plymphPerpendicular(rc, eqVar, xforplymph, pPer);
		go.setpPer(pPerp);
		String slope = "slope";
		Double pTangent = RStromalFactory.plymphTangent(rc, xforplymph, eqVar, pPer, pTan, slope);
		go.setpTangent(pTangent);
		Double pSpecific = RStromalFactory.plymphLymphSpecific(rc, timeGroupVar, pLymphSp, lymphSpecific);
		go.setpSpecific(pSpecific);
		RStromalPlotFactory.rorPlot(rc, ratioFile, rorPlot, pTan, pPer, pLymphSp, slope, "Tissue:Lymphoid Rank Ordered Ratio");
		go.setRorPlot(ratioFile);
		return go;

	}

	private static void ratio(RConnection rc, String geneList, String tableVar, String calculatedStromalVar, String ratioVar)
			throws REngineException, REXPMismatchException {
		RUtils.runRExp(rc, String.format("%s<<-NULL", ratioVar));
		String newVar = "new";
		RUtils.runRExp(rc, String.format("mean(%s[%s,])->%s", calculatedStromalVar, geneList, newVar));
		String oldVar = "old";
		RUtils.runRExp(rc, String.format("mean(%s[%s,1])->%s", tableVar, geneList, oldVar));
		RUtils.runRExp(rc, String.format("%s/%s->>%s", newVar, oldVar, ratioVar));

	}

	public static void setPLymph(RConnection rc, String pLymph, Double pLymphD) throws REngineException, REXPMismatchException {
		String calcPL = String.format("%s>%s", pLymph, pLymphD);
		System.out.println(calcPL);
		rc.parseAndEval(calcPL);
	}

	// as.character(unlist(read.table("LymphList.txt",sep="\t",
	// as.is=TRUE))->lymphSpecific

	// as.data.frame(NewVec)->CalculatedStroma
	//
	// colnames(CalculatedStroma)<- "Calculated Stroma"
	//
	// cbind(Both, CalculatedStroma)->Combined
	//
	// Symboler(Combined)

	// Symboler<-function(x){
	//
	// mget(rownames(x),mouse4302SYMBOL,ifnotfound=NA)->>symbs
	//
	// as.character(unlist(symbs))->>GeneSymbol
	//
	// mget(rownames(x),mouse4302ENTREZID,ifnotfound=NA)->>egs
	//
	// as.character(unlist(egs))->EntrezID
	//
	// cbind(GeneSymbol,EntrezID,x)->>ResultTable
	//
	// }

	public static void setRowNameColName(RConnection rc, String tableRowNamesFrom, String combinedTable) throws REngineException,
			REXPMismatchException {
		List<String> tables = new ArrayList<String>();
		String colNames = "colnames";
		RUtils.runRExp(rc, String.format("colnames(%s)->%s", tableRowNamesFrom, colNames));
		tables.add(String.format("rownames(%s)", tableRowNamesFrom));
		tables.add(tableRowNamesFrom);
		RUtils.cbind(rc, tables, combinedTable);
		RUtils.runRExp(rc, String.format("colnames(%s)<-c(\"Probe Set ID\",%s)", combinedTable, colNames));
	}

	public static File signalFile(RConnection rc, String table, String fileDescription, IdTable idTable, File path) throws REngineException,
			REXPMismatchException, IOException {
		RStromalFactory.addGeneEntrezIds(rc, table, idTable);
		RStromalFactory.setRowNameColName(rc, table, table + "2");
		File file = File.createTempFile(table + "_" + fileDescription + "_", ".txt", path);
		file.deleteOnExit();
		String fileS = file.getAbsolutePath().replace("\\", "/");
		// NewVec is defined in the NewOne function

		RUtils.writeTable(rc, table + "2", fileS, "TRUE", "FALSE");
		return file;

	}

	// public static File signalFile(RConnection rc, String table, Boolean log2)
	// throws REngineException, REXPMismatchException, IOException {
	// Integer precision = 0;
	// if (log2) {
	// RUtils.assign(rc, RUtils.log2(table), table);
	// precision = 2;
	// }
	// RUtils.assign(rc, RUtils.round(table, precision), table);
	// RStromalFactory.addGeneEntrezIds(rc, table);
	// RStromalFactory.setRowNameColName(rc, table, table + "2");
	// File file = File.createTempFile(table + "_", ".txt");
	// file.deleteOnExit();
	// String fileS = file.getAbsolutePath().replace("\\", "/");
	// // NewVec is defined in the NewOne function
	//
	// RUtils.writeTable(rc, table + "2", fileS, "TRUE", "FALSE");
	// return file;
	//
	// }

	public static File signalFile(RConnection rc, String table, String presentCallVar, Boolean log2, IdTable idTable) throws REngineException,
			REXPMismatchException, IOException {

		String filteredTableVar = "filteredTable";
		RUtils.assign(rc, RUtils.filterTable(table, presentCallVar, ""), filteredTableVar);
		if (log2)
			RUtils.assign(rc, RUtils.log2(filteredTableVar), filteredTableVar);
		RStromalFactory.addGeneEntrezIds(rc, filteredTableVar, idTable);
		RStromalFactory.setRowNameColName(rc, filteredTableVar, filteredTableVar + "2");
		File stromalFile = File.createTempFile(table + "_", ".txt");
		String stromalFileS = stromalFile.getAbsolutePath().replace("\\", "/");
		// NewVec is defined in the NewOne function

		RUtils.writeTable(rc, filteredTableVar + "2", stromalFileS, "TRUE", "FALSE");
		return stromalFile;

	}

	// m<<-3*eq[1]*xforplymph^2+ 2*eq[2]*xforplymph+eq[3];
	private static void slope(RConnection rc, String slope, String xforplymphVarName, String eqVarName) throws REngineException,
			REXPMismatchException {
		String mm = String.format("%s<<-3*%s[1]*%s^2+ 2*%s[2]*%s+%s[3];", slope, eqVarName, xforplymphVarName, eqVarName, xforplymphVarName,
				eqVarName);
		RUtils.runRExp(rc, mm);
	}

	public static File stromalCalc(RConnection rc, String wholePartVar, String pLymphVar) throws REngineException, REXPMismatchException, IOException {
		File stromalFile = File.createTempFile("stromal_", ".txt");
		String stromalFileS = stromalFile.getAbsolutePath().replace("\\", "/");
		String newOne = String.format("NewOne(%s, %s)", wholePartVar, pLymphVar);
		System.out.println(newOne);
		rc.parseAndEval(newOne);
		String combined = "averageAndStromal";
		// NewVec is defined in the NewOne function
		List<String> tables = new ArrayList<String>();
		tables.add(wholePartVar);
		tables.add("NewVec");
		RUtils.cbind(rc, tables, combined);
		RUtils.writeTable(rc, combined, stromalFileS, "NA", "TRUE");
		return stromalFile;

	}

	public static void stromalRatio(RConnection rc, String tableVar, String calculatedStromalVar, String stromalRatioVar) throws REngineException,
			REXPMismatchException {
		ratio(rc, "CortMFP", tableVar, calculatedStromalVar, stromalRatioVar);
	}

	// eq needs to be calculated first
	// xforplymph<-(-2*eq[2])/(6*eq[1]);
	public static void xforplymph(RConnection rc, String eqVar, String xforplymphVar) throws REngineException, REXPMismatchException {
		String xforplymph = String.format("%s<-(-2*%s[2])/(6*%s[1]);", xforplymphVar, eqVar, eqVar);
		System.out.println(xforplymph);
		rc.parseAndEval(xforplymph);
	}

}
